# -*- coding: utf-8 -*-
from .models import DevType, DevEname, Device, DevTaskJob
from django.shortcuts import render
from utils.cryption import Cryption
from utils.decorators import service_required
from utils.viewutil import get_user, ajaxresponse, pages, savelog
from apps.realtimeinfo.views import shell_getstatusoutput
import json
from apps.system.models import SysSetting
from datetime import datetime, timedelta
from .views import check_dev_can_use
from apps.core.templatetags.audittags import get_fortree_token
from apps.assetmgnt.controler import acquire_devsoft_version, change_syslog_file
import subprocess
from django.db.transaction import atomic


@service_required('sys_config')
def list_discover(request):
    """探测结果列表"""
    devs = DevTaskJob.objects.all()
    s, e, pagination = pages(request, devs)

    task_config = SysSetting.objects.filter(key_str="asset_task_config")
    if task_config.exists():
        task_config_value = json.loads(task_config.first().value_str)
        job_end_date = task_config_value.get("job_end_date")
        auto = task_config_value.get("auto")
        job_status = task_config_value.get("job_status")
        is_del = task_config_value.get("is_del")
    else:
        job_end_date = "未配置"
        auto = "未配置"
        job_status = "未开启"
        is_del = "未配置"

    device_ips = [each.ip for each in Device.objects.all()]
    return render(request, 'list_discover.html',
                  {'objs': devs[s: e], 'pagination': pagination, "job_status": job_status,
                   "job_end_date": job_end_date, "auto": auto, "device_ips": device_ips,
                   "is_del": is_del})


@service_required('sys_config')
def start_job(request):
    """探测任务编辑"""
    if request.POST:

        end_date = request.POST.get('end_date', '').strip()
        is_del = request.POST.get('is_del', "").strip()
        is_auto = request.POST.get('is_auto', '').strip()
        is_sum = request.POST.get('is_sum', '').strip()
        try:
            datetime.strptime(end_date, "%Y-%m-%d %H:%M")
        except:
            return ajaxresponse({'head': 'ERROR', 'body': u'结束时间格式不正确，正确格式：2001-01-01 12:12'})

        status, resp = shell_getstatusoutput("/usr/bin/passive_detection -i any -s start")
        print(resp)
        if not status:
            return ajaxresponse({'head': 'ERROR', 'body': u'开启资产探测失败， 原因：{}'.format(resp)})
        _value = json.dumps({"job_end_date": end_date,
                             "auto": is_auto,
                             "is_del": is_del,
                             "job_status": "进行中",
                             "is_sum": is_sum,
                             "task_id": resp},
                            ensure_ascii=False)
        task_config = SysSetting.objects.filter(key_str="asset_task_config")
        if not task_config.exists():
            SysSetting.objects.create(key_str="asset_task_config", value_str=_value, remark="探测任务配置")
        else:
            task_config.update(value_str=_value)
        if is_del == "是":
            DevTaskJob.objects.all().delete()

        return ajaxresponse({'head': 'OK', 'body': u'开启资产探测成功', 'redirect': '/assetmgnt/list_discover/'})
    else:
        return render(request, 'start_job.html', {"obj": []})


def stop_discover_job():
    dev_types = DevType.objects.filter(ename="other")
    if not dev_types.exists():
        dev_type = DevType.objects.create(name="探测任务自动确认类型", identify="discover_other", useradd=1,
                                          ename="other", desc="自动添加类型")
    else:
        dev_type = dev_types.first()
    auto = "否"
    with atomic():
        task_config = SysSetting.objects.filter(key_str="asset_task_config")
        if task_config.exists():
            _config = json.loads(task_config.first().value_str)
            is_sum = _config.get("is_sum")  # 合并
            auto = _config.get("auto")  # 自动添加到资产
            _config["job_status"] = "结束"
            status, resp = shell_getstatusoutput(
                f"/usr/bin/passive_detection -i any -s stop -id {_config.get('task_id')}")
            if not status:
                return ajaxresponse({'head': 'ERROR', 'body': u'停止探测任务成功失败， 原因：{}'.format(resp)})
            get_status, get_resp = shell_getstatusoutput(
                f"/usr/bin/passive_detection -i any -s get -id {_config.get('task_id')}")

            if get_status:
                for k, v in json.loads(get_resp).items():
                    _status = 0
                    if is_sum == "是":
                        # 合并，IP绑定
                        Device.objects.filter(ip=v.get("ipaddr")).update(vendor=v.get("service").get("vendor", ""),
                                                                         devnumber=v.get("service").get("osType", ""),
                                                                         model=v.get("service").get("model", ""))
                        _status = 2
                    if auto == "是" and not Device.objects.filter(ip=v.get("ipaddr")).exists():
                        # 自动添加到资产
                        dev = Device()
                        dev.name = f"自动确认-{v.get('ipaddr')}"
                        dev.dtype_id = dev_type.id
                        dev.model = v.get("service").get("model", "")
                        dev.mac = v.get("service").get("mac", "")
                        dev.ip = v.get("ipaddr")
                        dev.endtime = (datetime.utcnow() + timedelta(hours=8) + timedelta(days=30)).strftime("%Y-%m-%d")
                        dev.devnumber = v.get("service").get("osType", "")
                        dev.vendor = v.get("service").get("vendor", "")
                        dev.save()
                        _status = 1
                    DevTaskJob.objects.create(ip=v.get("ipaddr"), vendor=v.get("service").get("vendor", ""),
                                              model=v.get("service").get("model", ""),
                                              os_type=v.get("service").get("osType", ""), status=_status,
                                              mac=v.get("service").get("mac", ""))
            task_config.update(value_str=json.dumps(_config, ensure_ascii=False))
    if auto == "是":
        subprocess.run(
            '/usr/bin/python3.6 /usr/insec/safept/utils/eventmessage.py restart > /dev/console 2>&1',
            shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        change_syslog_file()
    return True


@service_required('sys_config')
def stop_job(request):
    """停止探测任务"""
    if request.POST:
        try:
            flag = stop_discover_job()
            if flag:
                return ajaxresponse({'head': 'OK', 'body': u'停止探测任务成功', 'redirect': '/assetmgnt/list_discover/'})
            else:
                return ajaxresponse({'head': 'ERROR', 'body': u'停止探测任务失败'})
        except Exception as e:
            return ajaxresponse({'head': 'ERROR', 'body': str(e), 'redirect': '/assetmgnt/list_discover/'})
    else:
        return render(request, 'stop_job.html', {"obj": []})


@service_required('sys_config')
def asset_merge(request):
    """资产间相互合并"""
    if request.POST:
        device_id = request.POST.get('device', '').strip()
        func_list = request.POST.getlist('func_list', '')
        device_select = request.POST.getlist('device_select', '')

        device = Device.objects.get(id=device_id)
        _data = {}
        for each in func_list:
            _data[each] = getattr(device, each)
        Device.objects.filter(id__in=device_select).update(**_data)
        return ajaxresponse({'head': 'OK', 'body': u'资产合并成功', 'redirect': '/assetmgnt/listdev/'})
        # return ajaxresponse({'head': 'OK', 'body': u'合并到资产成功', 'redirect': '/assetmgnt/asset_merge/'})
    else:
        device = Device.objects.all()
        func_dict = {
            "dtype_id": "设备类型",
            "importance": "重要程度",
            "location": "所处位置",
            "safeowner": "安全责任人",
            "devnumber": "设备型号",
            "mac": "MAC",
            "vendor": "厂商",
            "model": "版本",
        }
        return render(request, 'asset_merge.html', {"device": device, "func_dict": func_dict})


@service_required('sys_config')
def recover_discover(request):
    """探测结果合并到资产"""
    if request.POST:
        dev_task_id = request.POST.get('did', '').strip()
        func_list = request.POST.getlist('func_list', '')
        device_select = request.POST.getlist('device_select', '')
        dev_task = DevTaskJob.objects.get(id=dev_task_id)
        _data = {}
        for each in func_list:
            if each == "devnumber":
                _data[each] = dev_task.os_type
            else:
                _data[each] = getattr(dev_task, each)
        Device.objects.filter(id__in=device_select).update(**_data)
        dev_task.status = 2
        dev_task.save()
        return ajaxresponse({'head': 'OK', 'body': u'合并到资产成功', 'redirect': '/assetmgnt/list_discover/'})
    else:
        did = request.GET.get('did', '').strip()
        dev_task = DevTaskJob.objects.get(id=did)
        device = Device.objects.all()
        func_dict = {
            "devnumber": "设备型号",
            "mac": "MAC",
            "vendor": "厂商",
            "model": "版本",
        }
        return render(request, 'discover_asset_merge.html', {"device": device, "func_dict": func_dict, "dev_task": dev_task})


@service_required('sys_config')
def del_discover(request):
    """删除探测结果"""
    hid = request.GET.get('did', '').strip()
    DevTaskJob.objects.filter(id=hid).delete()
    return ajaxresponse({'head': 'OK', 'body': u'删除成功'})


@service_required('sys_config')
def add_discover(request):
    """探测结果添加"""
    if request.POST:
        user = get_user(request)
        dev = Device()
        dev.name = request.POST.get('name', '').strip()
        dev.dtype_id = int(request.POST.get('dtype', 0))
        try:
            if Device.objects.get(name=dev.name):
                return ajaxresponse({'head': 'ERROR', 'body': u'添加设备失败，此设备名称已存在'})
        except Exception:
            pass
        dev.mac = request.POST.get('mac', '').strip()
        dev.ip = request.POST.get('ip', '').strip()
        dev.endtime = request.POST.get('endtime', '')
        dev.devnumber = request.POST.get('devnumber', '').strip()
        dev.vendor = request.POST.get('vendor', '').strip()
        dev.model = request.POST.get('model', '').strip()
        dev.importance = int(request.POST.get('importance', 0))
        dev.location = request.POST.get('location', '')
        dev.safeowner = request.POST.get('safeowner', '')
        url = request.POST.get('url', '')
        # isauth = int(request.POST.get('isauthenticate', 0))
        isauth = 1
        username = request.POST.get('username', '').strip()
        password = request.POST.get('passwd', '').strip()
        dev_token = request.POST.get('dev_token', '')
        dtyp = DevType.objects.get(id=dev.dtype_id)
        dtypid = dtyp.ename
        if len(url):
            dev.desc = url
        if dtypid == 'IDS':
            dev.username = dev_token
            dev.passwd = ''
            res = check_dev_can_use(curip=dev.ip, dtype=dtypid, username=dev_token, pwd='')
            if not res:
                return ajaxresponse({'head': 'ERROR', 'body': u'设备鉴权失败,请输入有效的验证信息'})
        elif dtypid == "fortress_machine_V2":
            dev.username = username
            dev.passwd = ''
            res = get_fortree_token(dev.ip, username)
            # res = get_fortree_token("39.107.115.155:21043", username)
            if not res:
                return ajaxresponse({'head': 'ERROR', 'body': u'设备鉴权失败,请输入有效的验证信息'})
        elif dtypid[0:2] not in ("T3", 'A4', 'T9') and dtypid != "white-net" and dtypid != "LAS":
            dev.username = ''
            dev.passwd = ''
            isauth = 0
        else:
            dev.username = username
            dev.passwd = Cryption.encrypt(password + ',' + PASSWORD_KEY)
            res = check_dev_can_use(dev.ip, dtypid, username, password)
            if not res:
                return ajaxresponse({'head': 'ERROR', 'body': u'设备鉴权失败,请输入有效的验证信息'})
        devvision, softvision, sn = acquire_devsoft_version(dev.ip, dtypid)
        dev.assert_no = sn
        dev.hardnumber = devvision
        dev.version = softvision
        dev.isauthenticate = isauth
        dev.save()
        subprocess.run('/usr/bin/python3.6 /usr/insec/safept/utils/eventmessage.py restart > /dev/console 2>&1',
                       shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        change_syslog_file()
        did = request.POST.get('did', '').strip()
        dev_task = DevTaskJob.objects.get(id=did)
        dev_task.status = 1
        dev_task.save()
        savelog(request, 'config', u'系统', u'系统', 6, u'设备', u'%s添加设备，设备名称为：%s' % (user, dev.name))
        return ajaxresponse({'head': 'OK', 'body': u'设备添加成功', 'redirect': '/assetmgnt/list_discover/'})
    else:
        did = request.GET.get('did', '').strip()
        dev_task = DevTaskJob.objects.get(id=did)
        dev_type = DevType.objects.all()

        endtime = (datetime.utcnow() + timedelta(hours=8) + timedelta(days=30)).strftime("%Y-%m-%d")
        dev_task.endtime = endtime
        return render(request, 'task_add_asset.html', {"dev_task": dev_task, "dev_type": dev_type})
